package feces.utility;

import java.sql.Date;
import java.util.Arrays;
import java.util.Iterator;

import lombok.AccessLevel;
import lombok.NoArgsConstructor;

/**
 * 实用工具类
 *
 * @author Bromine0x23
 */
@NoArgsConstructor(access = AccessLevel.PRIVATE)
public final class Utility {

	/**
	 * 连接数组
	 *
	 * @param head 头数组
	 * @param tail 尾数组
	 * @return 连接后的数组
	 */
	@SafeVarargs
	public static <T> T[] concat(T[] head, T... tail) {
		T[] array = Arrays.copyOf(head, head.length + tail.length);
		System.arraycopy(tail, 0, array, head.length, tail.length);
		return array;
	}

	/**
	 * 连接数组
	 *
	 * @param head 头数组
	 * @param tail 尾元素
	 * @return 连接后的数组
	 */
	public static <T> T[] concat(T[] head, T tail) {
		T[] array = Arrays.copyOf(head, head.length + 1);
		array[head.length] = tail;
		return array;
	}

	/**
	 * 填充数组
	 *
	 * @param array 待填充数组
	 * @param element 填充元素
	 * @return 填充后的数组
	 */
	public static <E> E[] fill(E[] array, E element) {
		for (int i = 0; i < array.length; ++i) {
			array[i] = element;
		}
		return array;
	}

	/**
	 * 检测字符串是否为null或为空
	 *
	 * @param string 待检测字符串
	 * @return 检测结果
	 */
	public static boolean isEmpty(String string) {
		return string == null || string.isEmpty();
	}

	/**
	 * 检测字符串是否具有前缀
	 *
	 * @param string 待检测字符串
	 * @param prefix 前缀
	 * @return 检测结果
	 */
	public static boolean isStartWith(String string, String prefix) {
		return !isEmpty(string) && !isEmpty(prefix) && string.startsWith(prefix);
	}

	/**
	 * 转化可迭代对象元素为字符串，并拼接
	 *
	 * @param iterable 可迭代对象
	 * @return 拼接结果
	 */
	public static <T> String join(Iterable<T> iterable) {
		return join("", iterable);
	}

	/**
	 * 转化可迭代对象元素为字符串，并用指定分隔符拼接
	 *
	 * @param delim 分隔符
	 * @param iterable 可迭代对象
	 * @return 拼接结果
	 */
	public static <T> String join(String delim, Iterable<T> iterable) {
		StringBuilder builder = new StringBuilder();
		Iterator<T> iterator = iterable.iterator();
		if (iterator.hasNext()) {
			builder.append(iterator.next());
		}
		while (iterator.hasNext()) {
			builder.append(delim).append(iterator.next());
		}
		return builder.toString();
	}

	/**
	 * 转化数组元素为字符串，并用拼接
	 *
	 * @param iterable 可迭代对象
	 * @return 拼接结果
	 */
	@SafeVarargs
	public static <T> String join(T... objects) {
		return join("", objects);
	}

	/**
	 * 转化数组元素为字符串，并用指定分隔符拼接
	 *
	 * @param delim 分隔符
	 * @param iterable 可迭代对象
	 * @return 拼接结果
	 */
	@SafeVarargs
	public static <T> String join(String delim, T... objects) {
		return join(delim, Arrays.asList(objects));
	}
	
	/**
	 * 尝试解析字符串为Integer对象
	 * 失败时返回<pre>null</pre>
	 *
	 * @param s 待解析字符串
	 * @return 解析结果
	 */
	public static Integer toInteger(String s) {
		try {
			return Integer.parseInt(s);
		} catch (NumberFormatException exception) {
			return null;
		}
	}
	
	/**
	 * 尝试解析字符串为Double对象
	 * 失败时返回<pre>null</pre>
	 *
	 * @param s 待解析字符串
	 * @return 解析结果
	 */
	public static Double toDouble(String s) {
		try {
			return Double.parseDouble(s);
		} catch (NullPointerException | NumberFormatException exception) {
			return null;
		}
	}
	
	/**
	 * 尝试解析字符串为Date对象
	 * 失败时返回<pre>null</pre>
	 *
	 * @param s 待解析字符串
	 * @return 解析结果
	 */
	public static Date toDate(String s) {
		try {
			return Date.valueOf(s);
		} catch (IllegalArgumentException exception) {
			return null;
		}
	}
	
	/**
	 * 解析字符串为boolean值
	 * 仅当参数为<pre>"true"</pre>时返回<pre>true</pre>
	 *
	 * @param s 待解析字符串
	 * @return 解析结果
	 */
	public static boolean toBoolean(String s) {
		return Boolean.parseBoolean(s);
	}
	
	/**
	 * 解析字符为boolean值
	 * 仅当参数为<pre>'Y'</pre>时返回<pre>true</pre>
	 *
	 * @param s 待解析字符串
	 * @return 解析结果
	 */
	public static boolean toBoolean(Character c) {
		return (c != null && c == 'Y') ? Boolean.TRUE : Boolean.FALSE;
	}
	
	/**
	 * 解析字符串为Character对象
	 * 当字符串长度为1时返回<pre>s.charAt(0)</pre>
	 * 否则返回<pre>null</pre>
	 *
	 * @param s 待解析字符串
	 * @return 解析结果
	 */
	public static Character toCharacter(String s) {
		return s != null && s.length() > 0 ? s.charAt(0) : null;
	}
	
	/**
	 * 解析Boolean值为Character对象
	 * 当参数非空且为<pre>Boolean.TRUE</pre>时返回<pre>'Y'</pre>
	 * 否则返回<pre>'N'</pre>
	 *
	 * @param b Boolean值
	 * @return 解析结果
	 */
	public static char toCharacter(Boolean b) {
		return (b != null && b == Boolean.TRUE) ? 'Y' : 'N';
	}
	
	public static <E extends Enum<E>> E toEnum(Class<E> klass, String s) {
		try {
			return Enum.valueOf(klass, s);
		} catch (IllegalArgumentException | NullPointerException exception) {
			return null;
		}
	}
}
